HDU 5727 Necklace(二分图最大匹配)

题意:

$给定2\times N个珠子的环,其中N个为yang,N个为yin,N\le 9$
$给定M\le N\times N个限制关系$
$对于每个限制关系a_i, b_i,表示yang a_i会变暗如果与yin b_i相邻$
$求最少的暗淡yang珠子数$

分析:

$由于是环,所以固定第1个珠子为1,然后8!枚举yin珠子的排列$
$之后对于每2个yin珠子的间隔,与yang珠子建图,表示这个yang珠子不会暗淡$
$跑二分图匹配,最大匹配数就是最大的不会暗淡的$
$ans=n-maxMatch$
$实际上匈牙利很快,然后如果都不暗淡提前退出就可以过去了$
$集训队的不带剪枝都过去了,不知道为啥窝自带百倍常数$
$时间复杂度O(8!\times nm)$

代码:

//
//  Created by TaoSama on 2016-07-20
//  Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:102400000,102400000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 10 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

int n, m;
int conflict[N][N];
struct Edge {
    int v, nxt;
} edge[N * N];
int head[N], cnt;

void addEdge(int u, int v) {
    edge[cnt] = {v, head[u]};
    head[u] = cnt++;
}

int match[N], vis[N];
bool dfs(int u) {
    for(int i = head[u]; ~i; i = edge[i].nxt) {
        int v = edge[i].v;
        if(vis[v]) continue;
        vis[v] = true;
        if(match[v] == -1 || dfs(match[v])) {
            match[v] = u;
            return true;
        }
    }
    return false;
}

int hungary() {
    int matches = 0;
    memset(match, -1, sizeof match);
    for(int i = 1; i <= n; ++i) {
        memset(vis, 0, sizeof vis);
        matches += dfs(i);
    }
    return matches;
}

int main() {
#ifdef LOCAL
    freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);
    clock_t _ = clock();

    while(scanf("%d%d", &n, &m) == 2) {
        memset(conflict, 0, sizeof conflict);
        for(int i = 1; i <= m; ++i) {
            int u, v; scanf("%d%d", &u, &v);
            conflict[u][v] = 1; //yang yin
        }

        int ans = -INF;

        //yin
        int ord[N]; ord[n + 1] = 1;
        for(int i = 1; i <= n; ++i) ord[i] = i;
        do {
//            for(int i = 1; i <= n + 1; ++i) printf("%d ", ord[i]); puts("");

            cnt = 0; memset(head, -1, sizeof head);
            for(int i = 1; i <= n; ++i) { //gap
                int l = ord[i], r = ord[i + 1];
                for(int j = 1; j <= n; ++j) { //yang
                    if(conflict[j][l] || conflict[j][r]) continue;
//                    printf("%d, %d\n", i, j);
                    addEdge(i, j);
                }
            }
            if(cnt <= ans) continue;
            ans = max(ans, hungary());
            if(ans == n) break;
        } while(next_permutation(ord + 2, ord + n + 1));

        printf("%d\n", n - ans);
    }

#ifdef LOCAL
    printf("\nTime cost: %.2fs\n", 1.0 * (clock() - _) / CLOCKS_PER_SEC);
#endif
    return 0;
}